package biz

import (
	"context"
	"time"

	"github.com/go-kratos/kratos/v2/errors"
	"github.com/go-kratos/kratos/v2/log"

	pb "gitee.com/danqingzhao/go-dango/api/user/customer/v1"
	"gitee.com/danqingzhao/go-dango/pkg/common/core"
	"gitee.com/danqingzhao/go-dango/pkg/proto/settings"
	"gitee.com/danqingzhao/go-dango/pkg/third/orm"
)

const (
	ErrGetLoginAttemptsMSG = "failed to get user login attempts"
	ErrSetLoginAttemptsMSG = "failed to set user login attempts"
)

type LoginRecordModel struct {
	Id        uint32    `gorm:"column:id;primary_key;AUTO_INCREMENT;comment:编号" json:"id"`
	Username  string    `gorm:"column:username;type:varchar(50);comment:用户名" json:"username"`
	LoginTime time.Time `gorm:"column:login_time;autoCreateTime;comment:登录时间" json:"login_time"`
	IPAddress string    `gorm:"column:ip_address;type:varchar(108);comment:ip地址" json:"ip_address"`
	UserAgent string    `gorm:"column:user_agent;type:varchar(254);comment:客户端信息" json:"user_agent"`
	Status    bool      `gorm:"column:status;type:boolean;comment:是否登录成功" json:"status"`
}

func (m *LoginRecordModel) TableName() string {
	return "user_login_record"
}

type RecordRepo interface {
	CreateModel(context.Context, *LoginRecordModel) error
	ListModel(context.Context, orm.QueryParams) (int64, []LoginRecordModel, error)
	GetRemainLoginNum(context.Context, string) (uint32, error)
	SetRemainLoginNum(context.Context, string, uint32) error
}

type RecordUsecase struct {
	log        *log.Helper
	recordRepo RecordRepo
}

func NewRecordUsecase(logHelpers *settings.LogHelpers, lr RecordRepo) *RecordUsecase {
	return &RecordUsecase{log: logHelpers.Biz, recordRepo: lr}
}

func (uc *RecordUsecase) CreateLoginRecord(
	ctx context.Context,
	m LoginRecordModel,
) (*LoginRecordModel, *errors.Error) {
	if err := uc.recordRepo.CreateModel(ctx, &m); err != nil {
		rErr := core.NewGormError(err, pb.ErrorReason_CUSTOMER_CREATE_LOGIN_RECORD_ERROR.String(), nil)
		uc.log.WithContext(ctx).Error(rErr.Error())
		return nil, rErr
	}
	return &m, nil
}

func (uc *RecordUsecase) ListLoginRecord(
	ctx context.Context,
	page, size int,
	query map[string]any,
) (int64, []LoginRecordModel, *errors.Error) {
	qp := orm.QueryParams{
		Preloads: []string{},
		Query:    query,
		OrderBy:  []string{"id"},
		Limit:    max(size, 0),
		Offset:   max(page-1, 0),
		IsCount:  true,
	}
	count, ms, err := uc.recordRepo.ListModel(ctx, qp)
	if err != nil {
		rErr := core.NewGormError(err, pb.ErrorReason_CUSTOMER_LIST_LOGIN_RECORD_ERROR.String(), nil)
		uc.log.WithContext(ctx).Error(rErr.Error())
		return 0, nil, rErr
	}
	return count, ms, nil
}

func (uc *RecordUsecase) GetRemainLoginNum(ctx context.Context, username string) (uint32, error) {
	return uc.recordRepo.GetRemainLoginNum(ctx, username)
}

func (uc *RecordUsecase) SetRemainLoginNum(ctx context.Context, username string, num uint32) error {
	return uc.recordRepo.SetRemainLoginNum(ctx, username, num)
}
